home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 676-700 / 681 / term / source.lha / termXPR.c < prev    next >
C/C++ Source or Header  |  1992-05-09  |  46KB  |  2,060 lines

  1. /*
  2. **    $Id: termXPR.c,v 1.7 92/05/01 12:51:43 olsen Sta Locker: olsen $
  3. **    $Revision: 1.7 $
  4. **    $Date: 92/05/01 12:51:43 $
  5. **
  6. **    External transfer protocol support routines
  7. **
  8. **    Copyright © 1990-1992 by Olaf `Olsen' Barthel & MXM
  9. **        All Rights Reserved
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14.     /* How many options will xpr_options display in a single column. */
  15.  
  16. #define OPTION_WRAP 16
  17.  
  18.     /* These variables keep the transferred bytes and transfer
  19.      * time in seconds.
  20.      */
  21.  
  22. STATIC LONG         ByteVal,ByteMax,TimeVal,TimeMax;
  23.  
  24.     /* The name of the file being transmitted, in case the
  25.      * `override transfer path' feature is enabled.
  26.      */
  27.  
  28. STATIC UBYTE         RealName[256];
  29.  
  30. STATIC struct Buffer    *CurrentFile;
  31.  
  32.     /* Yet another flag, this one determines whether we already told
  33.      * the user that the file we are currently processing will fit
  34.      * on the destination device.
  35.      */
  36.  
  37. STATIC BYTE         Alerted;
  38.  
  39.     /* xpr_fopen(UBYTE *FileName,UBYTE *AccessMode):
  40.      *
  41.      *    Open a file for random access.
  42.      */
  43.  
  44. LONG __saveds __asm
  45. xpr_fopen(register __a0 UBYTE *FileName,register __a1 UBYTE *AccessMode)
  46. {
  47.     struct Buffer *File;
  48.  
  49.     Alerted = FALSE;
  50.  
  51.         /* Reset transfer counters. */
  52.  
  53.     ByteVal = ByteMax = TimeVal = TimeMax = 0;
  54.  
  55.         /* Disable the time and data bars in the transfer window. */
  56.  
  57.     if(TransferWindow)
  58.     {
  59.         GhostStats(TransferGadgetArray[2]);
  60.         GhostStats(TransferGadgetArray[3]);
  61.     }
  62.  
  63.         /* Remember file name. */
  64.  
  65.     strcpy(RealName,FileName);
  66.  
  67.         /* Build a new filename if neccessary. */
  68.  
  69.     if(Config . OverridePath)
  70.     {
  71.         if(!Uploading)
  72.         {
  73.             if(!DownloadPath)
  74.             {
  75.                 if(!Config . BinaryDownloadPath[0])
  76.                 {
  77.                     if(!GetCurrentDirName(RealName,256))
  78.                         RealName[0] = 0;
  79.                 }
  80.                 else
  81.                     strcpy(RealName,Config . BinaryDownloadPath);
  82.             }
  83.             else
  84.             {
  85.                 if(!DownloadPath[0])
  86.                 {
  87.                     if(!GetCurrentDirName(RealName,256))
  88.                         RealName[0] = 0;
  89.                 }
  90.                 else
  91.                     strcpy(RealName,DownloadPath);
  92.             }
  93.  
  94.             if(AddPart(RealName,FilePart(FileName),256))
  95.                 FileName = RealName;
  96.             else
  97.                 strcpy(RealName,FileName);
  98.         }
  99.     }
  100.  
  101.         /* Determine file transfer mode... */
  102.  
  103.     if(File = BufferOpen(FileName,AccessMode))
  104.     {
  105.         switch(AccessMode[0])
  106.         {
  107.             case 'r':    LogAction(LocaleString(MSG_TERMXPR_LOGMSG_SEND_FILE_TXT),FileName);
  108.                     break;
  109.  
  110.             case 'w':    LogAction(LocaleString(MSG_TERMXPR_LOGMSG_RECEIVE_FILE_TXT),FileName);
  111.                     AddDownloadObject(FileName);
  112.                     break;
  113.  
  114.             case 'a':    LogAction(LocaleString(MSG_TERMXPR_LOGMSG_UPDATE_FILE_TXT),FileName);
  115.                     break;
  116.         }
  117.  
  118.         CurrentFile = File;
  119.     }
  120.  
  121.     DidTransfer = TRUE;
  122.  
  123.     return((LONG)File);
  124. }
  125.  
  126.     /* xpr_fclose(struct Buffer *File):
  127.      *
  128.      *    Close a file opened by xpr_fopen.
  129.      */
  130.  
  131. LONG __saveds __asm
  132. xpr_fclose(register __a0 struct Buffer *File)
  133. {
  134.     BYTE WriteAccess = File -> WriteAccess;
  135.  
  136.         /* Close the file and see what it brings... */
  137.  
  138.     if(BufferClose(File))
  139.     {
  140.             /* Did we receive or send a file? */
  141.  
  142.         if(WriteAccess)
  143.         {
  144.             LONG Size;
  145.  
  146.                 /* Did the file remain empty? */
  147.  
  148.             if(!(Size = GetFileSize(RealName)))
  149.             {
  150.                 AddTransferInfo(LocaleString(MSG_TERMXPR_FILE_REMOVED_TXT),FilePart(RealName));
  151.  
  152.                     /* Delete empty file. */
  153.  
  154.                 if(DeleteFile(RealName))
  155.                     LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_REMOVED_TXT),RealName);
  156.                 else
  157.                     LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  158.             }
  159.             else
  160.             {
  161.                 if(ByteMax)
  162.                 {
  163.                     if(Size == ByteMax)
  164.                         AddTransferInfo(LocaleString(MSG_TERMXPR_FILE_RECEIVED_TXT),FilePart(RealName));
  165.                     else
  166.                         AddTransferInfo(LocaleString(MSG_TERMXPR_INCOMPLETE_FILE_RECEIVED_TXT),FilePart(RealName));
  167.                 }
  168.                     /* Try to identify the file type. */
  169.  
  170.                 Identify(RealName);
  171.  
  172.                 LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_BYTES_TXT),RealName,Size);
  173.             }
  174.         }
  175.         else
  176.         {
  177.                 /* Set the archived bit on files we uploaded? */
  178.  
  179.             if(Config . SetArchivedBit)
  180.             {
  181.                 BPTR FileLock;
  182.  
  183.                     /* Get a lock on it. */
  184.  
  185.                 if(FileLock = Lock(RealName,ACCESS_READ))
  186.                 {
  187.                     struct FileInfoBlock __aligned FileInfo;
  188.  
  189.                         /* Examine the file. */
  190.  
  191.                     if(Examine(FileLock,&FileInfo))
  192.                     {
  193.                             /* Remove the lock. */
  194.  
  195.                         UnLock(FileLock);
  196.  
  197.                             /* Set the `archived' bit. */
  198.  
  199.                         SetProtection(RealName,FileInfo . fib_Protection | FIBF_ARCHIVE);
  200.                     }
  201.                     else
  202.                         UnLock(FileLock);
  203.                 }
  204.             }
  205.  
  206.             AddTransferInfo(LocaleString(MSG_TERMXPR_FILE_SENT_TXT),FilePart(RealName));
  207.  
  208.             LogAction(LocaleString(MSG_TERMXPR_CLOSE_FILE_TXT),RealName);
  209.         }
  210.     }
  211.  
  212.     RealName[0] = 0;
  213.  
  214.     CurrentFile = NULL;
  215.  
  216.     return(1);
  217. }
  218.  
  219.     /* xpr_fread(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  220.      *
  221.      *    Read a few bytes from a file.
  222.      */
  223.  
  224. LONG __saveds __asm
  225. xpr_fread(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 LONG Count,register __a1 struct Buffer *File)
  226. {
  227.     return(BufferRead(File,Buffer,Size * Count) / Size);
  228. }
  229.  
  230.     /* xpr_fwrite(APTR Buffer,LONG Size,LONG Count,struct Buffer *File):
  231.      *
  232.      *    Write a few bytes to a file.
  233.      */
  234.  
  235. LONG __saveds __asm
  236. xpr_fwrite(register __a0 APTR Buffer,register __d0 LONG Size,register __d1 LONG Count,register __a1 struct Buffer *File)
  237. {
  238.     return(BufferWrite(File,Buffer,Size * Count) / Size);
  239. }
  240.  
  241.     /* xpr_fseek(struct Buffer *File,LONG Offset,LONG Origin):
  242.      *
  243.      *    Move the read/write pointer in a file.
  244.      */
  245.  
  246. LONG __saveds __asm
  247. xpr_fseek(register __a0 struct Buffer *File,register __d0 LONG Offset,register __d1 LONG Origin)
  248. {
  249.     return(BufferSeek(File,Offset,Origin) ? 0 : -1);
  250. }
  251.  
  252.     /* xpr_sread(UBYTE *Buffer,LONG Size,LONG Timeout):
  253.      *
  254.      *    Read a few bytes from the serial port (including
  255.      *    timeouts).
  256.      */
  257.  
  258. ULONG __saveds __asm
  259. xpr_sread(register __a0 UBYTE *Buffer,register __d0 ULONG Size,register __d1 LONG Timeout)
  260. {
  261.         /* Valid parameters? */
  262.  
  263.     if(WriteRequest && Size)
  264.     {
  265.             /* How many bytes are still in the serial buffer? */
  266.  
  267.         WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  268.  
  269.         DoIO(WriteRequest);
  270.  
  271.             /* No timeout specified? Return as many bytes
  272.              * as are currently within the buffer.
  273.              */
  274.  
  275.         if(Timeout < 1)
  276.         {
  277.                 /* Are there any bytes in the buffer? */
  278.  
  279.             if(WriteRequest -> IOSer . io_Actual > 0)
  280.             {
  281.                     /* More bytes available than requested? */
  282.  
  283.                 if(Size < WriteRequest -> IOSer . io_Actual)
  284.                     ReadRequest -> IOSer . io_Length = Size;
  285.                 else
  286.                     ReadRequest -> IOSer . io_Length = WriteRequest -> IOSer . io_Actual;
  287.  
  288.                     /* Fill the buffer. */
  289.  
  290.                 ReadRequest -> IOSer . io_Command    = CMD_READ;
  291.                 ReadRequest -> IOSer . io_Data        = Buffer;
  292.  
  293.                 if(!DoIO(ReadRequest))
  294.                     return(ReadRequest -> IOSer . io_Actual);
  295.             }
  296.         }
  297.         else
  298.         {
  299.             if(WriteRequest -> IOSer . io_Actual < Size)
  300.             {
  301.                 register ULONG SignalSet;
  302.  
  303.                     /* Set up the timer. */
  304.  
  305.                 TimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  306.                 TimeRequest -> tr_time . tv_secs    = Timeout >= MILLION ? Timeout / MILLION : 0;
  307.                 TimeRequest -> tr_time . tv_micro    = Timeout % MILLION;
  308.  
  309.                     /* Set up the read request. */
  310.  
  311.                 ReadRequest -> IOSer . io_Command    = CMD_READ;
  312.                 ReadRequest -> IOSer . io_Data        = Buffer;
  313.                 ReadRequest -> IOSer . io_Length    = Size;
  314.  
  315.                     /* Prevent early termination. */
  316.  
  317.                 SetSignal(0,SIG_SERIAL | SIG_TIMER);
  318.  
  319.                     /* Start IO... */
  320.  
  321.                 SendIO(ReadRequest);
  322.                 SendIO(TimeRequest);
  323.  
  324.                 FOREVER
  325.                 {
  326.                         /* Build signal mask. */
  327.  
  328.                     if(TransferWindow)
  329.                         SignalSet = SIG_SERIAL | SIG_TIMER | (1 << TransferWindow -> UserPort -> mp_SigBit);
  330.                     else
  331.                         SignalSet = SIG_SERIAL | SIG_TIMER;
  332.  
  333.                         /* Wait for either of both IORequests to return. */
  334.  
  335.                     SignalSet = Wait(SignalSet);
  336.  
  337.                         /* Hit by timeout? */
  338.  
  339.                     if(SignalSet & SIG_TIMER)
  340.                     {
  341.                             /* Abort the read request. */
  342.  
  343.                         AbortIO(ReadRequest);
  344.                         WaitIO(ReadRequest);
  345.  
  346.                             /* Remove the timer request. */
  347.  
  348.                         WaitIO(TimeRequest);
  349.  
  350.                             /* Did the driver receive any
  351.                              * data?
  352.                              */
  353.  
  354.                         if(!ReadRequest -> IOSer . io_Actual)
  355.                         {
  356.                                 /* Take a second look and query the number of
  357.                                  * bytes ready to be received, there may
  358.                                  * still be some bytes in the buffer.
  359.                                  * Note: this depends on the way the
  360.                                  * driver handles read abort.
  361.                                  */
  362.  
  363.                             WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  364.  
  365.                             DoIO(WriteRequest);
  366.  
  367.                                 /* Are there any bytes to transfer? */
  368.  
  369.                             if(WriteRequest -> IOSer . io_Actual > 0)
  370.                             {
  371.                                     /* Don't read more than actually wanted. */
  372.  
  373.                                 if(Size < WriteRequest -> IOSer . io_Actual)
  374.                                     ReadRequest -> IOSer . io_Length = Size;
  375.                                 else
  376.                                     ReadRequest -> IOSer . io_Length = WriteRequest -> IOSer . io_Actual;
  377.  
  378.                                 ReadRequest -> IOSer . io_Command    = CMD_READ;
  379.                                 ReadRequest -> IOSer . io_Data        = Buffer;
  380.  
  381.                                     /* Read the data. */
  382.  
  383.                                 if(!DoIO(ReadRequest))
  384.                                     return(ReadRequest -> IOSer . io_Actual);
  385.                                 else
  386.                                     return(0);
  387.                             }
  388.                             else
  389.                                 return(0);
  390.                         }
  391.                         else
  392.                             return(ReadRequest -> IOSer . io_Actual);
  393.                     }
  394.  
  395.                         /* Receive buffer filled? */
  396.  
  397.                     if(SignalSet & SIG_SERIAL)
  398.                     {
  399.                         AbortIO(TimeRequest);
  400.                         WaitIO(TimeRequest);
  401.  
  402.                         WaitIO(ReadRequest);
  403.  
  404.                         if(!ReadRequest -> IOSer . io_Error)
  405.                             return(ReadRequest -> IOSer . io_Actual);
  406.                         else
  407.                             return(0);
  408.                     }
  409.  
  410.                         /* Check the transfer window for
  411.                          * possible user abort.
  412.                          */
  413.  
  414.                     if(TransferWindow)
  415.                     {
  416.                         if(SignalSet & (1 << TransferWindow -> UserPort -> mp_SigBit))
  417.                         {
  418.                             if(xpr_chkabort() == -1)
  419.                             {
  420.                                 AbortIO(ReadRequest);
  421.                                 AbortIO(TimeRequest);
  422.  
  423.                                 WaitIO(ReadRequest);
  424.                                 WaitIO(TimeRequest);
  425.  
  426.                                 SendAbort = TRUE;
  427.  
  428.                                 return(-1);
  429.                             }
  430.                         }
  431.                     }
  432.                 }
  433.             }
  434.             else
  435.             {
  436.                 ReadRequest -> IOSer . io_Command    = CMD_READ;
  437.                 ReadRequest -> IOSer . io_Data        = Buffer;
  438.                 ReadRequest -> IOSer . io_Length    = Size;
  439.  
  440.                 if(!DoIO(ReadRequest))
  441.                     return(Size);
  442.             }
  443.         }
  444.     }
  445.  
  446.     return(0);
  447. }
  448.  
  449.     /* xpr_swrite(UBYTE *Buffer,LONG Size):
  450.      *
  451.      *    Write a few bytes to the serial port.
  452.      */
  453.  
  454. LONG __saveds __asm
  455. xpr_swrite(register __a0 UBYTE *Buffer,register __d0 LONG Size)
  456. {
  457.     if(WriteRequest)
  458.     {
  459.         WriteRequest -> IOSer . io_Command    = CMD_WRITE;
  460.         WriteRequest -> IOSer . io_Data        = Buffer;
  461.         WriteRequest -> IOSer . io_Length    = Size;
  462.  
  463.         return((LONG)DoIO(WriteRequest));
  464.     }
  465.     else
  466.         return(-1);
  467. }
  468.  
  469.     /* xpr_sflush():
  470.      *
  471.      *    Release the contents of all serial buffers.
  472.      */
  473.  
  474. LONG __saveds
  475. xpr_sflush()
  476. {
  477.     if(WriteRequest)
  478.     {
  479.         WriteRequest -> IOSer . io_Command = CMD_CLEAR;
  480.  
  481.         return((LONG)DoIO(WriteRequest));
  482.     }
  483.     else
  484.         return(-1);
  485. }
  486.  
  487.     /* GetSeconds(UBYTE *String):
  488.      *
  489.      *    Tries to turn a string of the format hh:mm:ss into
  490.      *    an integer number.
  491.      */
  492.  
  493. STATIC LONG __regargs
  494. GetSeconds(UBYTE *String)
  495. {
  496.     UBYTE    Buffer[20];
  497.     LONG    Seconds = 0;
  498.  
  499.     memset(Buffer,0,20);
  500.  
  501.     strcpy(Buffer,String);
  502.  
  503.     Seconds += atol(&Buffer[6]);
  504.  
  505.     Buffer[5] = 0;
  506.  
  507.     Seconds += atol(&Buffer[3]) * 60;
  508.  
  509.     Buffer[2] = 0;
  510.  
  511.     Seconds += atol(&Buffer[0]) * 3600;
  512.  
  513.     return(Seconds);
  514. }
  515.  
  516.     /* TruncateName(UBYTE *FileName):
  517.      *
  518.      *    Truncates a file name to a maximum of 48 characters.
  519.      */
  520.  
  521. STATIC UBYTE * __regargs
  522. TruncateName(UBYTE *FileName)
  523. {
  524.     WORD Len = strlen(FileName);
  525.  
  526.     if(Len > 48)
  527.     {
  528.         WORD i;
  529.  
  530.         for(i = Len - 48 ; i < Len ; i++)
  531.         {
  532.             if(i >= Len - 44 && FileName[i] == '/')
  533.             {
  534.                 STATIC UBYTE NameBuffer[256];
  535.  
  536.                 strcpy(NameBuffer,".../");
  537.  
  538.                 strcat(NameBuffer,&FileName[i + 1]);
  539.  
  540.                 return(NameBuffer);
  541.             }
  542.         }
  543.     }
  544.  
  545.     return(FileName);
  546. }
  547.  
  548.     /* CalculateBlocks(LONG Size,LONG BlockSize):
  549.      *
  550.      *    Calculate the number of blocks a file will
  551.      *    occupy if saved to a disk.
  552.      */
  553.  
  554. STATIC LONG __regargs
  555. CalculateBlocks(LONG Size,LONG BlockSize)
  556. {
  557.     LONG    Blocks        = 1;        /* One for the file header. */
  558.     BYTE    HasExtension    = FALSE,    /* No extension block yet. */
  559.         Extension    = 0;        /* How many block pointers yet. */
  560.  
  561.         /* Round to next block. */
  562.  
  563.     Size = ((Size + BlockSize - 1) / BlockSize) * BlockSize;
  564.  
  565.     while(Size)
  566.     {
  567.             /* Add another block. */
  568.  
  569.         Blocks++;
  570.  
  571.             /* Subtract another block. */
  572.  
  573.         Size -= BlockSize;
  574.  
  575.             /* Add another block pointer, if 72 have been
  576.              * added, add another extension block.
  577.              */
  578.  
  579.         if((Extension++) == 72)
  580.         {
  581.                 /* If no extension block has been generated
  582.                  * yet, we were running on the block pointers
  583.                  * of the file header itself.
  584.                  */
  585.  
  586.             if(!HasExtension)
  587.                 HasExtension = TRUE;
  588.             else
  589.                 Blocks++;
  590.  
  591.                 /* Reset extension block counter. */
  592.  
  593.             Extension = 0;
  594.         }
  595.     }
  596.  
  597.     return(Blocks);
  598. }
  599.  
  600.     /* xpr_update(struct XPR_UPDATE *UpdateInfo):
  601.      *
  602.      *    Update the information displayed in the transfer window.
  603.      */
  604.  
  605. LONG __saveds __asm
  606. xpr_update(register __a0 struct XPR_UPDATE *UpdateInfo)
  607. {
  608.     if(!TransferWindow)
  609.     {
  610.         BlockWindows();
  611.  
  612.         LogAction(LocaleString(MSG_TERMXPR_LOGMSG_INITIATE_BINARY_DOWNLOAD_TXT));
  613.  
  614.         if(!TransferPanel(LocaleString(MSG_TERMXPR_RECEIVE_FILES_TXT)))
  615.         {
  616.             ReleaseWindows();
  617.  
  618.             return(0);
  619.         }
  620.     }
  621.  
  622.     if(UpdateInfo)
  623.     {
  624.         BYTE    NewByte = FALSE,
  625.             NewTime = FALSE;
  626.  
  627.         if((UpdateInfo -> xpru_updatemask & XPRU_PROTOCOL) && UpdateInfo -> xpru_protocol)
  628.         {
  629.             GT_SetGadgetAttrs(TransferGadgetArray[4],TransferWindow,NULL,
  630.                 GTTX_Text,    UpdateInfo -> xpru_protocol,
  631.             TAG_DONE);
  632.         }
  633.  
  634.         if((UpdateInfo -> xpru_updatemask & XPRU_MSG) && UpdateInfo -> xpru_msg)
  635.         {
  636.             GT_SetGadgetAttrs(TransferGadgetArray[5],TransferWindow,NULL,
  637.                 GTTX_Text,    UpdateInfo -> xpru_msg,
  638.             TAG_DONE);
  639.         }
  640.  
  641.         if((UpdateInfo -> xpru_updatemask & XPRU_ERRORMSG) && UpdateInfo -> xpru_errormsg)
  642.             AddTransferInfo(UpdateInfo -> xpru_errormsg);
  643.  
  644.         if((UpdateInfo -> xpru_updatemask & XPRU_FILENAME) && UpdateInfo -> xpru_filename)
  645.         {
  646.             if(Config . OverridePath && !Uploading)
  647.             {
  648.                 if(!RealName[0])
  649.                 {
  650.                     if(!DownloadPath)
  651.                         strcpy(RealName,&Config . BinaryDownloadPath[0]);
  652.                     else
  653.                         strcpy(RealName,DownloadPath);
  654.  
  655.                     if(!AddPart(RealName,FilePart(UpdateInfo -> xpru_filename),256))
  656.                         strcpy(RealName,UpdateInfo -> xpru_filename);
  657.                 }
  658.  
  659.                 TransferInfo(19, 0,"%-48.48s",TruncateName(RealName));
  660.             }
  661.             else
  662.                 TransferInfo(19, 0,"%-48.48s",TruncateName(UpdateInfo -> xpru_filename));
  663.         }
  664.  
  665.         if((UpdateInfo -> xpru_updatemask & XPRU_FILESIZE) && UpdateInfo -> xpru_filesize != -1)
  666.         {
  667.             if(CurrentFile -> DirLock && CurrentFile -> InfoData . id_NumBlocks && CurrentFile -> InfoData . id_BytesPerBlock)
  668.                 TransferInfo(19, 1,ConvNumber10,UpdateInfo -> xpru_filesize);
  669.             else
  670.                 TransferInfo(19, 1,ConvNumber,UpdateInfo -> xpru_filesize);
  671.  
  672.             if(ByteMax = UpdateInfo -> xpru_filesize)
  673.                 NewByte = TRUE;
  674.         }
  675.  
  676.         if((UpdateInfo -> xpru_updatemask & XPRU_BYTES) && UpdateInfo -> xpru_bytes != -1)
  677.         {
  678.             TransferInfo(19, 4,ConvNumber,ByteVal = UpdateInfo -> xpru_bytes);
  679.  
  680.             if(ByteMax)
  681.                 NewByte = TRUE;
  682.  
  683.             if(CurrentFile -> DirLock && !Uploading)
  684.             {
  685.                 if(CurrentFile -> InfoData . id_NumBlocks && CurrentFile -> InfoData . id_BytesPerBlock)
  686.                 {
  687.                     if(ByteMax)
  688.                     {
  689.                         register LONG Blocks = CalculateBlocks(ByteMax,CurrentFile -> InfoData . id_BytesPerBlock),Space = CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed;
  690.  
  691.                         TransferInfo(19, 2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),Space * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks,(Space < Blocks) ? LocaleString(MSG_TERMXPR_FILE_MAY_NOT_FIT_TXT) : "");
  692.  
  693.                             /* Tell the user that he might be
  694.                              * running into trouble.
  695.                              */
  696.  
  697.                         if(!Alerted && (Space < Blocks))
  698.                         {
  699.                             Alerted = TRUE;
  700.  
  701.                             BumpWindow(TransferWindow);
  702.  
  703.                             Say(LocaleString(MSG_TERMXPR_SAY_FILE_MAY_NOT_FIT_TXT));
  704.                         }
  705.                     }
  706.                     else
  707.                         TransferInfo(19, 2,LocaleString(MSG_TERMXPR_BYTES_FULL_TXT),(CurrentFile -> InfoData . id_NumBlocks - CurrentFile -> InfoData . id_NumBlocksUsed) * CurrentFile -> InfoData . id_BytesPerBlock,100 * (CurrentFile -> InfoData . id_NumBlocksUsed) / CurrentFile -> InfoData . id_NumBlocks);
  708.                 }
  709.             }
  710.         }
  711.  
  712.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKS) && UpdateInfo -> xpru_blocks != -1)
  713.             TransferInfo(19, 5,ConvNumber,UpdateInfo -> xpru_blocks);
  714.  
  715.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKSIZE) && UpdateInfo -> xpru_blocksize != -1)
  716.             TransferInfo(19, 6,ConvNumber,UpdateInfo -> xpru_blocksize);
  717.  
  718.         if((UpdateInfo -> xpru_updatemask & XPRU_BLOCKCHECK) && UpdateInfo -> xpru_blockcheck)
  719.             TransferInfo(19, 7,"%-12.12s",UpdateInfo -> xpru_blockcheck);
  720.  
  721.         if((UpdateInfo -> xpru_updatemask & XPRU_EXPECTTIME) && UpdateInfo -> xpru_expecttime)
  722.         {
  723.             TransferInfo(19, 9,"%-12.12s",UpdateInfo -> xpru_expecttime);
  724.  
  725.             if(TimeMax = GetSeconds((UBYTE *)UpdateInfo -> xpru_expecttime))
  726.                 NewTime = TRUE;
  727.         }
  728.  
  729.         if((UpdateInfo -> xpru_updatemask & XPRU_ELAPSEDTIME) && UpdateInfo -> xpru_elapsedtime)
  730.         {
  731.             TransferInfo(19,10,"%-12.12s",UpdateInfo -> xpru_elapsedtime);
  732.  
  733.             TimeVal = GetSeconds((UBYTE *)UpdateInfo -> xpru_elapsedtime);
  734.  
  735.             if(TimeMax)
  736.                 NewTime = TRUE;
  737.         }
  738.  
  739.         if((UpdateInfo -> xpru_updatemask & XPRU_DATARATE) && UpdateInfo -> xpru_datarate != -1)
  740.             TransferInfo(54, 4,ConvNumber,UpdateInfo -> xpru_datarate);
  741.  
  742.         if((UpdateInfo -> xpru_updatemask & XPRU_CHARDELAY) && UpdateInfo -> xpru_chardelay != -1)
  743.             TransferInfo(54, 5,ConvNumber,UpdateInfo -> xpru_chardelay);
  744.  
  745.         if((UpdateInfo -> xpru_updatemask & XPRU_PACKETDELAY) && UpdateInfo -> xpru_packetdelay != -1)
  746.             TransferInfo(54, 6,ConvNumber,UpdateInfo -> xpru_packetdelay);
  747.  
  748.         if((UpdateInfo -> xpru_updatemask & XPRU_PACKETTYPE) && UpdateInfo -> xpru_packettype != -1)
  749.         {
  750.             if(UpdateInfo -> xpru_packettype > 31 && UpdateInfo -> xpru_packettype < 256)
  751.             {
  752.                 if(ValidTab[UpdateInfo -> xpru_packettype])
  753.                     TransferInfo(54, 7,"`%lc'",UpdateInfo -> xpru_packettype);
  754.                 else
  755.                     TransferInfo(54, 7,ConvNumber,UpdateInfo -> xpru_packettype);
  756.             }
  757.             else
  758.                 TransferInfo(54, 7,ConvNumber,UpdateInfo -> xpru_packettype);
  759.         }
  760.  
  761.         if((UpdateInfo -> xpru_updatemask & XPRU_ERRORS) && UpdateInfo -> xpru_errors != -1)
  762.             TransferInfo(54, 9,ConvNumber,UpdateInfo -> xpru_errors);
  763.  
  764.         if((UpdateInfo -> xpru_updatemask & XPRU_TIMEOUTS) && UpdateInfo -> xpru_timeouts != -1)
  765.             TransferInfo(54,10,ConvNumber,UpdateInfo -> xpru_timeouts);
  766.  
  767.         if(TransferWindow)
  768.         {
  769.             if(NewByte)
  770.             {
  771.                 ShowStats(TransferGadgetArray[2],ByteVal,ByteMax);
  772.  
  773.                 if(ByteMax)
  774.                     ShowString(TransferGadgetArray[2],"%3ld%%",(100 * ByteVal) / ByteMax);
  775.                 else
  776.                     ShowString(TransferGadgetArray[2],"%3ld%%",0);
  777.             }
  778.  
  779.             if(NewTime)
  780.             {
  781.                 LONG TimeDif = (TimeMax - TimeVal) < 0 ? 0 : TimeMax - TimeVal;
  782.  
  783.                 ShowStats(TransferGadgetArray[3],TimeDif,TimeMax);
  784.  
  785.                 ShowString(TransferGadgetArray[3],"%2ld:%02ld:%02ld",TimeDif / 3600,(TimeDif / 60) % 60,TimeDif % 60);
  786.             }
  787.         }
  788.     }
  789.  
  790.     return(1);
  791. }
  792.  
  793.     /* xpr_chkabort():
  794.      *
  795.      *    Check if the user has aborted the transfer.
  796.      */
  797.  
  798. LONG __saveds
  799. xpr_chkabort()
  800. {
  801.     LONG Result = 0;
  802.  
  803.     if(TransferWindow)
  804.     {
  805.         struct IntuiMessage    *Massage;
  806.         ULONG             Class,Code;
  807.         struct Gadget        *Gadget;
  808.  
  809.         while(Massage = (struct IntuiMessage *)GT_GetIMsg(TransferWindow -> UserPort))
  810.         {
  811.             Class    = Massage -> Class;
  812.             Code    = Massage -> Code;
  813.             Gadget    = (struct Gadget *)Massage -> IAddress;
  814.  
  815.             GT_ReplyIMsg(Massage);
  816.  
  817.             if(!Result)
  818.             {
  819.                 if(Class == IDCMP_VANILLAKEY)
  820.                     KeySelect(TransferGadgetArray,1,Code,TransferWindow,&Gadget,&Class,&Code);
  821.  
  822.                 if(Class == IDCMP_NEWSIZE)
  823.                 {
  824.                     if(!(TransferWindow -> Flags & WFLG_ZOOMED))
  825.                         RefreshTransferWindow();
  826.                 }
  827.  
  828.                 if(Class == IDCMP_CLOSEWINDOW)
  829.                 {
  830.                     LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  831.  
  832.                     TransferAborted = TRUE;
  833.  
  834.                     Result = -1;
  835.                 }
  836.  
  837.                 if(Class == IDCMP_GADGETUP)
  838.                 {
  839.                     switch(Gadget -> GadgetID)
  840.                     {
  841.                         case 0:    LogAction(LocaleString(MSG_TERMXPR_LOGMSG_TRANSFER_ABORTED_TXT));
  842.  
  843.                             TransferAborted = TRUE;
  844.  
  845.                             Result = -1;
  846.                             break;
  847.  
  848.                         case 1:    LogAction(LocaleString(MSG_TERMXPR_LOGMSG_FILE_SKIPPED_TXT));
  849.  
  850.                             Result = 1;
  851.                             break;
  852.  
  853.                         default:break;
  854.                     }
  855.                 }
  856.             }
  857.         }
  858.     }
  859.  
  860.     return(Result);
  861. }
  862.  
  863.     /* The following subroutine creates the gadgets required by
  864.      * xpr_gets().
  865.      */
  866.  
  867. struct Gadget *
  868. CreateAllGetsGadgets(BYTE LoadGadget,UBYTE *String,UBYTE *Prompt,LONG *WindowWidth,struct Gadget **GadgetArray,struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge,struct Screen *Screen)
  869. {
  870.     struct Gadget        *Gadget;
  871.     struct NewGadget     NewGadget;
  872.  
  873.     memset(&NewGadget,0,sizeof(struct NewGadget));
  874.  
  875.     if(Gadget = CreateContext(GadgetList))
  876.     {
  877.         WORD Width = strlen(Prompt),Counter = 0;
  878.  
  879.         if(Width < 40)
  880.             Width = 40;
  881.  
  882.         NewGadget . ng_Width        = Width * 8 + 6;
  883.         NewGadget . ng_Height        = 14;
  884.         NewGadget . ng_GadgetText    = Prompt;
  885.         NewGadget . ng_TextAttr        = &DefaultFont;
  886.         NewGadget . ng_VisualInfo    = VisualInfo;
  887.         NewGadget . ng_GadgetID        = Counter;
  888.         NewGadget . ng_Flags        = PLACETEXT_ABOVE;
  889.         NewGadget . ng_LeftEdge        = 10;
  890.         NewGadget . ng_TopEdge        = 1 + TopEdge + 8 + 8;
  891.  
  892.         GadgetArray[Counter++] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  893.             GTST_MaxChars,    255,
  894.             GTST_String,    String,
  895.             GTST_EditHook,    &CommandHook,
  896.             GA_Immediate,    TRUE,
  897.         TAG_DONE);
  898.  
  899.         if(Gadget)
  900.             *WindowWidth = Gadget -> Width + 32;
  901.         else
  902.             *WindowWidth = 200;
  903.  
  904.         NewGadget . ng_Width        = 88;
  905.         NewGadget . ng_Height        = 12;
  906.         NewGadget . ng_GadgetText    = LocaleString(MSG_TERMXPR_OKAY_GAD);
  907.         NewGadget . ng_GadgetID        = Counter;
  908.         NewGadget . ng_Flags        = 0;
  909.         NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + NewGadget . ng_Height + 3;
  910.  
  911.         GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  912.             GT_Underscore,    '_',
  913.         TAG_DONE);
  914.  
  915.         if(LoadGadget)
  916.         {
  917.             NewGadget . ng_Width        = 88;
  918.             NewGadget . ng_GadgetText    = LocaleString(MSG_TERMXPR_LOAD_FILE_GAD);
  919.             NewGadget . ng_GadgetID        = Counter;
  920.             NewGadget . ng_LeftEdge        = (*WindowWidth - NewGadget . ng_Width) >> 1;
  921.  
  922.             GadgetArray[Counter++] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  923.                 GT_Underscore,    '_',
  924.             TAG_DONE);
  925.         }
  926.         else
  927.             Counter++;
  928.  
  929.         NewGadget . ng_Width        = 88;
  930.         NewGadget . ng_GadgetText    = LocaleString(MSG_GLOBAL_CANCEL_GAD);
  931.         NewGadget . ng_GadgetID        = Counter;
  932.         NewGadget . ng_LeftEdge        = GadgetArray[0] -> LeftEdge + GadgetArray[0] -> Width + 6 - NewGadget . ng_Width;
  933.  
  934.         GadgetArray[Counter] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  935.             GT_Underscore,    '_',
  936.         TAG_DONE);
  937.     }
  938.  
  939.     return(Gadget);
  940. }
  941.  
  942.     /* xpr_gets(UBYTE *Prompt,UBYTE *Buffer):
  943.      *
  944.      *    Prompt the user for string input.
  945.      */
  946.  
  947. LONG __saveds __asm
  948. xpr_gets(register __a0 UBYTE *Prompt,register __a1 UBYTE *Buffer)
  949. {
  950.     struct Gadget    *GadgetList = NULL;
  951.     struct Gadget    *GadgetArray[4];
  952.     struct Window    *PanelWindow;
  953.     LONG         Width,Success = FALSE;
  954.  
  955.     if(!Prompt)
  956.         Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
  957.  
  958.     if(CreateAllGetsGadgets(FALSE,Buffer,Prompt,&Width,&GadgetArray[0],&GadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1,Screen))
  959.     {
  960.         if(PanelWindow = OpenWindowTags(NULL,
  961.             WA_Width,    Width,
  962.             WA_Height,    58,
  963.  
  964.             WA_Left,    (Screen -> Width - Width) >> 1,
  965.             WA_Top,        (Screen -> Height - 56) >> 1,
  966.  
  967.             WA_Activate,    TRUE,
  968.             WA_DragBar,    TRUE,
  969.             WA_DepthGadget,    TRUE,
  970.             WA_CloseGadget,    TRUE,
  971.             WA_RMBTrap,    TRUE,
  972.             WA_CustomScreen,Screen,
  973.  
  974.             WA_IDCMP,    IDCMP_GADGETDOWN | IDCMP_ACTIVEWINDOW | IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | BUTTONIDCMP | STRINGIDCMP,
  975.  
  976.             WA_Title,    LocaleString(MSG_GLOBAL_ENTER_TEXT_TXT),
  977.         TAG_DONE))
  978.         {
  979.             struct IntuiMessage    *Massage;
  980.             ULONG             Class,Code;
  981.             struct Gadget        *Gadget;
  982.             BYTE             Terminated = FALSE;
  983.  
  984.             PushWindow(PanelWindow);
  985.  
  986.             AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  987.             RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
  988.             GT_RefreshWindow(PanelWindow,NULL);
  989.  
  990.             ActiveGadget = NULL;
  991.  
  992.             while(!Terminated)
  993.             {
  994.                 WaitPort(PanelWindow -> UserPort);
  995.  
  996.                 while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
  997.                 {
  998.                     Class    = Massage -> Class;
  999.                     Code    = Massage -> Code;
  1000.                     Gadget    = (struct Gadget *)Massage -> IAddress;
  1001.  
  1002.                     GT_ReplyIMsg(Massage);
  1003.  
  1004.                     if(Class == IDCMP_VANILLAKEY)
  1005.                         KeySelect(GadgetArray,3,Code,PanelWindow,&Gadget,&Class,&Code);
  1006.  
  1007.                     if(Class == IDCMP_GADGETDOWN)
  1008.                     {
  1009.                         if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  1010.                             ActiveGadget = Gadget;
  1011.                     }
  1012.  
  1013.                     if(Class == IDCMP_GADGETDOWN)
  1014.                     {
  1015.                         if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  1016.                             ActiveGadget = Gadget;
  1017.                     }
  1018.  
  1019.                     if(Class == IDCMP_ACTIVEWINDOW && ActiveGadget)
  1020.                         ActivateGadget(ActiveGadget,PanelWindow,NULL);
  1021.  
  1022.                     if(Class == IDCMP_CLOSEWINDOW)
  1023.                         Terminated = TRUE;
  1024.  
  1025.                     if(Class == IDCMP_GADGETUP)
  1026.                     {
  1027.                         switch(Gadget -> GadgetID)
  1028.                         {
  1029.                             case 0: if(Code != '\t')
  1030.                                 {
  1031.                                     strcpy(Buffer,GT_STRING(GadgetArray[0]));
  1032.  
  1033.                                     Success = TRUE;
  1034.  
  1035.                                     Terminated = TRUE;
  1036.                                     break;
  1037.                                 }
  1038.  
  1039.                             case 1:    strcpy(Buffer,GT_STRING(GadgetArray[0]));
  1040.  
  1041.                                 Success = TRUE;
  1042.  
  1043.                                 Terminated = TRUE;
  1044.                                 break;
  1045.  
  1046.                             case 3:    Terminated = TRUE;
  1047.                                 break;
  1048.                         }
  1049.                     }
  1050.                 }
  1051.             }
  1052.  
  1053.             ActiveGadget = NULL;
  1054.  
  1055.             RemoveGList(PanelWindow,GadgetList,(UWORD)-1);
  1056.  
  1057.             PopWindow();
  1058.  
  1059.             CloseWindow(PanelWindow);
  1060.         }
  1061.  
  1062.         FreeGadgets(GadgetList);
  1063.     }
  1064.  
  1065.     return(Success);
  1066. }
  1067.  
  1068.     /* xpr_setserial(LONG Status):
  1069.      *
  1070.      *    Set/read the serial status (parameters).
  1071.      */
  1072.  
  1073. LONG __saveds __asm
  1074. xpr_setserial(register __d0 LONG Status)
  1075. {
  1076.     if(WriteRequest)
  1077.     {
  1078.         STATIC LONG XprBauds[12] =
  1079.         {
  1080.                110,
  1081.                300,
  1082.               1200,
  1083.               2400,
  1084.               4800,
  1085.               9600,
  1086.              19200,
  1087.              31250,
  1088.              38400,
  1089.              57600,
  1090.              76800,
  1091.             115200
  1092.         };
  1093.  
  1094.         LONG Return,i;
  1095.  
  1096.         WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  1097.  
  1098.         DoIO(WriteRequest);
  1099.  
  1100.         Return = WriteRequest -> io_SerFlags & 0xFF;
  1101.  
  1102.         if(WriteRequest -> io_ExtFlags & SEXTF_MSPON)
  1103.             Return |= ST_PARTYMARKON;
  1104.  
  1105.         if(WriteRequest -> io_ExtFlags & SEXTF_MARK)
  1106.             Return |= ST_PARTYMARK;
  1107.  
  1108.         if(WriteRequest -> io_StopBits == 2)
  1109.             Return |= ST_2BITS;
  1110.  
  1111.         if(WriteRequest -> io_ReadLen == 7)
  1112.             Return |= ST_READ7;
  1113.  
  1114.         if(WriteRequest -> io_WriteLen == 7)
  1115.             Return |= ST_WRITE7;
  1116.  
  1117.         for(i = 0 ; i < 12 ; i++)
  1118.         {
  1119.             if(WriteRequest -> io_Baud <= XprBauds[i])
  1120.             {
  1121.                 Return |= (i << 16);
  1122.  
  1123.                 break;
  1124.             }
  1125.         }
  1126.  
  1127.         if(Status != -1)
  1128.         {
  1129.             WriteRequest -> IOSer . io_Command    = SDCMD_SETPARAMS;
  1130.  
  1131.             WriteRequest -> io_SerFlags        = Status & 0xFF;
  1132.             WriteRequest -> io_ExtFlags        = 0;
  1133.  
  1134.             if(Status & ST_PARTYMARKON)
  1135.                 WriteRequest -> io_ExtFlags |= SEXTF_MSPON;
  1136.  
  1137.             if(Status & ST_PARTYMARK)
  1138.                 WriteRequest -> io_ExtFlags |= SEXTF_MARK;
  1139.  
  1140.             if(Status & ST_2BITS)
  1141.                 WriteRequest -> io_StopBits = 2;
  1142.             else
  1143.                 WriteRequest -> io_StopBits = 1;
  1144.  
  1145.             if(Status & ST_READ7)
  1146.                 WriteRequest -> io_ReadLen = 7;
  1147.             else
  1148.                 WriteRequest -> io_ReadLen = 8;
  1149.  
  1150.             if(Status & ST_WRITE7)
  1151.                 WriteRequest -> io_WriteLen = 7;
  1152.             else
  1153.                 WriteRequest -> io_WriteLen = 8;
  1154.  
  1155.             DoIO(WriteRequest);
  1156.  
  1157.             ReadRequest -> io_SerFlags    = WriteRequest -> io_SerFlags;
  1158.             ReadRequest -> io_ExtFlags    = WriteRequest -> io_ExtFlags;
  1159.  
  1160.             ReadRequest -> io_StopBits    = WriteRequest -> io_StopBits;
  1161.             ReadRequest -> io_ReadLen    = WriteRequest -> io_ReadLen;
  1162.             ReadRequest -> io_WriteLen    = WriteRequest -> io_WriteLen;
  1163.         }
  1164.  
  1165.         return(Return);
  1166.     }
  1167.     else
  1168.         return(-1);
  1169. }
  1170.  
  1171.     /* xpr_ffirst(UBYTE *Buffer,UBYTE *Pattern):
  1172.      *
  1173.      *    Batch file upload: find the first matching file and return
  1174.      *    its name.
  1175.      */
  1176.  
  1177. LONG __saveds __asm
  1178. xpr_ffirst(register __a0 UBYTE *Buffer,register __a1 UBYTE *Pattern)
  1179. {
  1180.     if(MultipleFiles)
  1181.     {
  1182.         FileCount = 0;
  1183.  
  1184.         strcpy(Buffer,FileArg[FileCount++] . wa_Name);
  1185.  
  1186.         return(1);
  1187.     }
  1188.     else
  1189.     {
  1190.         FileMatch = TRUE;
  1191.  
  1192.         if(!MatchFirst(Pattern,FileAnchor))
  1193.         {
  1194.             if(FileAnchor -> ap_Info . fib_DirEntryType < 0)
  1195.             {
  1196.                 strcpy(Buffer,FileAnchor -> ap_Info . fib_FileName);
  1197.  
  1198.                 return(1);
  1199.             }
  1200.             else
  1201.             {
  1202.                 while(!MatchNext(FileAnchor))
  1203.                 {
  1204.                     if(FileAnchor -> ap_Info . fib_DirEntryType < 0)
  1205.                     {
  1206.                         strcpy(Buffer,FileAnchor -> ap_Info . fib_FileName);
  1207.  
  1208.                         return(1);
  1209.                     }
  1210.                 }
  1211.             }
  1212.         }
  1213.     }
  1214.  
  1215.     return(0);
  1216. }
  1217.  
  1218.     /* xpr_fnext(LONG OldState,UBYTE *Buffer,UBYTE *Pattern):
  1219.      *
  1220.      *    Batch file upload: find the next matching file
  1221.      *    - if any - and return its name.
  1222.      */
  1223.  
  1224. LONG __saveds __asm
  1225. xpr_fnext(register __d0 LONG OldState,register __a0 UBYTE *Buffer,register __a1 UBYTE *Pattern)
  1226. {
  1227.     if(MultipleFiles)
  1228.     {
  1229.         if(FileCount < FileCountMax)
  1230.         {
  1231.             strcpy(Buffer,FileArg[FileCount++] . wa_Name);
  1232.  
  1233.             return(1);
  1234.         }
  1235.     }
  1236.     else
  1237.     {
  1238.         FileMatch = TRUE;
  1239.  
  1240.         while(!MatchNext(FileAnchor))
  1241.         {
  1242.             if(FileAnchor -> ap_Info . fib_DirEntryType < 0)
  1243.             {
  1244.                 strcpy(Buffer,FileAnchor -> ap_Info . fib_FileName);
  1245.  
  1246.                 return(1);
  1247.             }
  1248.         }
  1249.     }
  1250.  
  1251.     return(0);
  1252. }
  1253.  
  1254.     /* xpr_finfo(UBYTE *FileName,LONG InfoType):
  1255.      *
  1256.      *    Return information on a given file.
  1257.      */
  1258.  
  1259. LONG __saveds __asm
  1260. xpr_finfo(register __a0 UBYTE *FileName,register __d0 LONG InfoType)
  1261. {
  1262.     BPTR FileLock;
  1263.  
  1264.     switch(InfoType)
  1265.     {
  1266.         case 1:    if(Config . OverridePath && !Uploading)
  1267.             {
  1268.                 if(!DownloadPath)
  1269.                 {
  1270.                     if(!Config . BinaryDownloadPath[0])
  1271.                     {
  1272.                         if(!GetCurrentDirName(RealName,256))
  1273.                             RealName[0] = 0;
  1274.                     }
  1275.                     else
  1276.                         strcpy(RealName,Config . BinaryDownloadPath);
  1277.                 }
  1278.                 else
  1279.                 {
  1280.                     if(!DownloadPath[0])
  1281.                     {
  1282.                         if(!GetCurrentDirName(RealName,256))
  1283.                             RealName[0] = 0;
  1284.                     }
  1285.                     else
  1286.                         strcpy(RealName,DownloadPath);
  1287.                 }
  1288.  
  1289.                 if(AddPart(RealName,FilePart(FileName),256))
  1290.                     FileName = RealName;
  1291.             }
  1292.  
  1293.             if(FileLock = Lock(FileName,ACCESS_READ))
  1294.             {
  1295.                 struct FileInfoBlock __aligned    FileInfo;
  1296.                 register LONG            Size;
  1297.  
  1298.                 if(Examine(FileLock,&FileInfo))
  1299.                     Size = FileInfo . fib_Size;
  1300.                 else
  1301.                     Size = 0;
  1302.  
  1303.                 UnLock(FileLock);
  1304.  
  1305.                 return(Size);
  1306.             }
  1307.  
  1308.             break;
  1309.  
  1310.         case 2:    return(BinaryTransfer ? 1 : 2);
  1311.     }
  1312.  
  1313.     return(0);
  1314. }
  1315.  
  1316.     /* The following routines are to support the xpr_options function. */
  1317.  
  1318. STATIC BYTE __regargs
  1319. GetOptionMode(struct xpr_option *Option)
  1320. {
  1321.     if(Option)
  1322.     {
  1323.         if(!Stricmp(Option -> xpro_value,"OFF"))
  1324.             return(FALSE);
  1325.  
  1326.         if(!Stricmp(Option -> xpro_value,"FALSE"))
  1327.             return(FALSE);
  1328.  
  1329.         if(!Stricmp(Option -> xpro_value,"F"))
  1330.             return(FALSE);
  1331.  
  1332.         if(!Stricmp(Option -> xpro_value,"NO"))
  1333.             return(FALSE);
  1334.  
  1335.         if(!Stricmp(Option -> xpro_value,"N"))
  1336.             return(FALSE);
  1337.  
  1338.  
  1339.         if(!Stricmp(Option -> xpro_value,"ON"))
  1340.             return(TRUE);
  1341.  
  1342.         if(!Stricmp(Option -> xpro_value,"TRUE"))
  1343.             return(TRUE);
  1344.  
  1345.         if(!Stricmp(Option -> xpro_value,"T"))
  1346.             return(TRUE);
  1347.  
  1348.         if(!Stricmp(Option -> xpro_value,"YES"))
  1349.             return(TRUE);
  1350.  
  1351.         if(!Stricmp(Option -> xpro_value,"Y"))
  1352.             return(TRUE);
  1353.     }
  1354.  
  1355.     return(FALSE);
  1356. }
  1357.  
  1358. STATIC struct Gadget *
  1359. CreateAllOptionGadgets(LONG *Count,LONG *Width,LONG *Height,LONG NumOpts,struct xpr_option *Opts[],struct Gadget *GadgetArray[],struct Gadget **GadgetList,APTR VisualInfo,UWORD TopEdge)
  1360. {
  1361.     struct Gadget        *Gadget;
  1362.     struct NewGadget     NewGadget;
  1363.     LONG             i,MaxLength = 0,MaxLength1 = 0,AddTop = 0,Len,LeftPlus = 0,MaxRight = 0,MaxWidth = 0,NumOptsSmall,Tmp;
  1364.  
  1365.     memset(&NewGadget,0,sizeof(struct NewGadget));
  1366.  
  1367.     *Count = 0;
  1368.  
  1369.     if(Gadget = CreateContext(GadgetList))
  1370.     {
  1371.         NewGadget . ng_TopEdge        = TopEdge + 1;
  1372.         NewGadget . ng_Height        = 12;
  1373.         NewGadget . ng_Width        = 208;
  1374.  
  1375.         NewGadget . ng_TextAttr        = &DefaultFont;
  1376.         NewGadget . ng_VisualInfo    = VisualInfo;
  1377.         NewGadget . ng_Flags        = NG_HIGHLABEL;
  1378.  
  1379.             /* Precalculate gadget left edge offset. */
  1380.  
  1381.         if((NumOptsSmall = NumOpts) > OPTION_WRAP)
  1382.             NumOptsSmall = OPTION_WRAP;
  1383.  
  1384.         for(i = 0 ; i < NumOptsSmall ; i++)
  1385.         {
  1386.             if(Opts[i])
  1387.             {
  1388.                 switch(Opts[i] -> xpro_type)
  1389.                 {
  1390.                     case XPRO_BOOLEAN:
  1391.                     case XPRO_LONG:
  1392.                     case XPRO_STRING:
  1393.                     case XPRO_COMMPAR:
  1394.  
  1395.                         if((Len = strlen(Opts[i] -> xpro_description)) > MaxLength)
  1396.                             MaxLength = Len;
  1397.  
  1398.                         break;
  1399.  
  1400.                     case XPRO_COMMAND:
  1401.  
  1402.                         if(MaxLength < 25)
  1403.                             MaxLength = 25;
  1404.  
  1405.                         break;
  1406.  
  1407.                     default:
  1408.  
  1409.                         break;
  1410.                 }
  1411.             }
  1412.         }
  1413.  
  1414.         if(MaxLength < 16)
  1415.             MaxLength = 16;
  1416.  
  1417.         if(MaxLength < 25)
  1418.             MaxLength = (25 - MaxLength) * 8;
  1419.         else
  1420.             MaxLength = 0;
  1421.  
  1422.         for(i = OPTION_WRAP ; i < NumOpts ; i++)
  1423.         {
  1424.             if(Opts[i])
  1425.             {
  1426.                 switch(Opts[i] -> xpro_type)
  1427.                 {
  1428.                     case XPRO_BOOLEAN:
  1429.                     case XPRO_LONG:
  1430.                     case XPRO_STRING:
  1431.                     case XPRO_COMMPAR:
  1432.  
  1433.                         if((Len = strlen(Opts[i] -> xpro_description)) > MaxLength1)
  1434.                             MaxLength1 = Len;
  1435.  
  1436.                         break;
  1437.  
  1438.                     case XPRO_COMMAND:
  1439.  
  1440.                         if(MaxLength1 < 25)
  1441.                             MaxLength1 = 25;
  1442.  
  1443.                         break;
  1444.  
  1445.                     default:
  1446.  
  1447.                         break;
  1448.                 }
  1449.             }
  1450.         }
  1451.  
  1452.         if(MaxLength1 < 16)
  1453.             MaxLength1 = 16;
  1454.  
  1455.         if(MaxLength1 < 25)
  1456.             MaxLength1 = (25 - MaxLength1) * 8;
  1457.         else
  1458.             MaxLength1 = 0;
  1459.  
  1460.         *Height    = 0;
  1461.  
  1462.         for(i = 0 ; i < NumOpts ; i++)
  1463.         {
  1464.             if(!Opts[i])
  1465.                 continue;
  1466.  
  1467.             switch(Opts[i] -> xpro_type)
  1468.             {
  1469.                 case XPRO_BOOLEAN:
  1470.  
  1471.                     NewGadget . ng_GadgetText    = Opts[i] -> xpro_description;
  1472.                     NewGadget . ng_GadgetID        = i;
  1473.                     NewGadget . ng_Width        = 26;
  1474.                     NewGadget . ng_Height        = 11;
  1475.                     NewGadget . ng_LeftEdge        = 218 - MaxLength + LeftPlus;
  1476.                     NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + AddTop;
  1477.  
  1478.                     GadgetArray[i] = Gadget = CreateGadget(CHECKBOX_KIND,Gadget,&NewGadget,
  1479.                         GTCB_Checked,    GetOptionMode(Opts[i]),
  1480.                     TAG_DONE);
  1481.  
  1482.                     break;
  1483.  
  1484.                 case XPRO_LONG:
  1485.  
  1486.                     NewGadget . ng_GadgetText    = Opts[i] -> xpro_description;
  1487.                     NewGadget . ng_GadgetID        = i;
  1488.                     NewGadget . ng_LeftEdge        = 218 - MaxLength + LeftPlus;
  1489.                     NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + AddTop;
  1490.                     NewGadget . ng_Height        = 14;
  1491.  
  1492.                     GadgetArray[i] = Gadget = CreateGadget(INTEGER_KIND,Gadget,&NewGadget,
  1493.                         GTIN_Number,    atol(Opts[i] -> xpro_value),
  1494.                         GTST_EditHook,    &CommandHook,
  1495.                         GA_Immediate,    TRUE,
  1496.                     TAG_DONE);
  1497.  
  1498.                     break;
  1499.  
  1500.                 case XPRO_STRING:
  1501.                 case XPRO_COMMPAR:
  1502.  
  1503.                     NewGadget . ng_GadgetText    = Opts[i] -> xpro_description;
  1504.                     NewGadget . ng_GadgetID        = i;
  1505.                     NewGadget . ng_LeftEdge        = 218 - MaxLength + LeftPlus;
  1506.                     NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + AddTop;
  1507.                     NewGadget . ng_Height        = 14;
  1508.  
  1509.                     GadgetArray[i] = Gadget = CreateGadget(STRING_KIND,Gadget,&NewGadget,
  1510.                         GTST_String,    Opts[i] -> xpro_value,
  1511.                         GTST_MaxChars,    Opts[i] -> xpro_length - 1,
  1512.                         GTST_EditHook,    &CommandHook,
  1513.                         GA_Immediate,    TRUE,
  1514.                     TAG_DONE);
  1515.  
  1516.                     break;
  1517.  
  1518.                 case XPRO_HEADER:
  1519.  
  1520.                     NewGadget . ng_GadgetText    = "";
  1521.                     NewGadget . ng_GadgetID        = i;
  1522.                     NewGadget . ng_LeftEdge        = 10 + LeftPlus;
  1523.                     NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + AddTop;
  1524.                     NewGadget . ng_Flags        = 0;
  1525.                     NewGadget . ng_Height        = 8;
  1526.                     NewGadget . ng_Width        = 8 * strlen(Opts[i] -> xpro_description);
  1527.  
  1528.                     GadgetArray[i] = Gadget = CreateGadget(TEXT_KIND,Gadget,&NewGadget,
  1529.                         GTTX_Text,    Opts[i] -> xpro_description,
  1530.                     TAG_DONE);
  1531.  
  1532.                     break;
  1533.  
  1534.                 case XPRO_COMMAND:
  1535.  
  1536.                     NewGadget . ng_GadgetText    = Opts[i] -> xpro_description;
  1537.                     NewGadget . ng_GadgetID        = i;
  1538.                     NewGadget . ng_LeftEdge        = 10 + LeftPlus;
  1539.                     NewGadget . ng_TopEdge        = NewGadget . ng_TopEdge + 13;
  1540.  
  1541.                     GadgetArray[i] = Gadget = CreateGadget(BUTTON_KIND,Gadget,&NewGadget,
  1542.                         TAG_DONE);
  1543.  
  1544.                     break;
  1545.  
  1546.                 default:break;
  1547.             }
  1548.  
  1549.             if(MaxWidth < (Tmp = NewGadget . ng_LeftEdge + NewGadget .ng_Width + 10))
  1550.                 MaxWidth = Tmp;
  1551.  
  1552.             AddTop = NewGadget . ng_Height + 1;
  1553.  
  1554.             if(i < OPTION_WRAP)
  1555.             {
  1556.                 if(NewGadget . ng_LeftEdge + NewGadget . ng_Width > MaxRight)
  1557.                     MaxRight = NewGadget . ng_LeftEdge + NewGadget . ng_Width;
  1558.  
  1559.                 if(i == OPTION_WRAP - 1)
  1560.                 {
  1561.                     LeftPlus = MaxRight;
  1562.  
  1563.                     *Height    = NewGadget . ng_TopEdge + NewGadget . ng_Height + 3;
  1564.  
  1565.                     MaxLength = MaxLength1;
  1566.  
  1567.                     NewGadget . ng_TopEdge = TopEdge + 1;
  1568.  
  1569.                     AddTop = 0;
  1570.                 }
  1571.             }
  1572.  
  1573.             if(i < NumOpts - 1)
  1574.             {
  1575.                 NewGadget . ng_Height    = 12;
  1576.                 NewGadget . ng_Width    = 208;
  1577.                 NewGadget . ng_Flags    = NG_HIGHLABEL;
  1578.             }
  1579.         }
  1580.  
  1581.         if(Gadget)
  1582.         {
  1583.             if(NewGadget . ng_TopEdge + NewGadget . ng_Height + 3 > *Height)
  1584.                 *Height = NewGadget . ng_TopEdge + NewGadget . ng_Height + 3;
  1585.  
  1586.             *Count    = i;
  1587.             *Width    = MaxWidth;
  1588.         }
  1589.     }
  1590.  
  1591.     return(Gadget);
  1592. }
  1593.  
  1594.     /* xpr_options(LONG NumOpts,struct xpr_option **Opts):
  1595.      *
  1596.      *    Provide a more polished user interface to set the
  1597.      *    transfer protocol options.
  1598.      */
  1599.  
  1600. ULONG __saveds __asm
  1601. xpr_options(register __d0 LONG NumOpts,register __a0 struct xpr_option **Opts)
  1602. {
  1603.     struct Gadget    *GadgetList = NULL;
  1604.     struct Gadget    *GadgetArray[34];
  1605.     struct Window    *PanelWindow;
  1606.     LONG         Width,Height,i,Count;
  1607.  
  1608.     ULONG         Flags = 0;
  1609.  
  1610.     if(CreateAllOptionGadgets(&Count,&Width,&Height,NumOpts,Opts,&GadgetArray[0],&GadgetList,VisualInfo,Screen -> WBorTop + Screen -> Font -> ta_YSize + 1))
  1611.     {
  1612.         if(PanelWindow = OpenWindowTags(NULL,
  1613.             WA_Width,    Width,
  1614.             WA_Height,    Height,
  1615.  
  1616.             WA_Left,    (Screen -> Width - Width) >> 1,
  1617.             WA_Top,        (Screen -> Height - Height) >> 1,
  1618.  
  1619.             WA_Activate,    TRUE,
  1620.             WA_DragBar,    TRUE,
  1621.             WA_DepthGadget,    TRUE,
  1622.             WA_CloseGadget,    TRUE,
  1623.             WA_RMBTrap,    TRUE,
  1624.             WA_CustomScreen,Screen,
  1625.  
  1626.             WA_IDCMP,    IDCMP_GADGETDOWN | IDCMP_ACTIVEWINDOW | IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | CHECKBOXIDCMP | STRINGIDCMP | INTEGERIDCMP | BUTTONIDCMP,
  1627.  
  1628.             WA_Title,    OptionTitle ? OptionTitle : LocaleString(MSG_TERMXPR_TRANSFER_OPTIONS_TXT),
  1629.         TAG_DONE))
  1630.         {
  1631.             struct IntuiMessage    *Massage;
  1632.             ULONG             Class,Code;
  1633.             struct Gadget        *Gadget;
  1634.             BYTE             Terminated = FALSE;
  1635.  
  1636.             PushWindow(PanelWindow);
  1637.  
  1638.             AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  1639.             RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
  1640.             GT_RefreshWindow(PanelWindow,NULL);
  1641.  
  1642.             ActiveGadget = NULL;
  1643.  
  1644.             while(!Terminated)
  1645.             {
  1646.                 WaitPort(PanelWindow -> UserPort);
  1647.  
  1648.                 while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
  1649.                 {
  1650.                     Class    = Massage -> Class;
  1651.                     Code    = Massage -> Code;
  1652.                     Gadget    = (struct Gadget *)Massage -> IAddress;
  1653.  
  1654.                     GT_ReplyIMsg(Massage);
  1655.  
  1656.                     if(Class == IDCMP_VANILLAKEY)
  1657.                         KeySelect(GadgetArray,Count,Code,PanelWindow,&Gadget,&Class,&Code);
  1658.  
  1659.                     if(Class == IDCMP_GADGETDOWN)
  1660.                     {
  1661.                         if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  1662.                             ActiveGadget = Gadget;
  1663.                     }
  1664.  
  1665.                     if(Class == IDCMP_ACTIVEWINDOW && ActiveGadget)
  1666.                         ActivateGadget(ActiveGadget,PanelWindow,NULL);
  1667.  
  1668.                     if(Class == IDCMP_CLOSEWINDOW)
  1669.                         Terminated = TRUE;
  1670.  
  1671.                     if(Class == IDCMP_GADGETUP)
  1672.                     {
  1673.                         if(Gadget -> GadgetID < NumOpts)
  1674.                         {
  1675.                             if(Opts[Gadget -> GadgetID] -> xpro_type == XPRO_COMMAND)
  1676.                             {
  1677.                                 Flags |= (1 << Gadget -> GadgetID);
  1678.  
  1679.                                 Terminated = TRUE;
  1680.                             }
  1681.                         }
  1682.                     }
  1683.  
  1684.                     if(Terminated)
  1685.                     {
  1686.                         if(!OptionTitle)
  1687.                             NewOptions = FALSE;
  1688.  
  1689.                         for(i = 0 ; i < NumOpts ; i++)
  1690.                         {
  1691.                             switch(Opts[i] -> xpro_type)
  1692.                             {
  1693.                                 case XPRO_BOOLEAN:    if(GT_CHECKED(GadgetArray[i]) != GetOptionMode(Opts[i]))
  1694.                                             {
  1695.                                                 Flags |= (1 << i);
  1696.  
  1697.                                                 if(GT_CHECKED(GadgetArray[i]))
  1698.                                                     strcpy(Opts[i] -> xpro_value,"yes");
  1699.                                                 else
  1700.                                                     strcpy(Opts[i] -> xpro_value,"no");
  1701.  
  1702.                                                 if(!OptionTitle)
  1703.                                                     NewOptions = TRUE;
  1704.                                             }
  1705.                                             break;
  1706.  
  1707.                                 case XPRO_COMMPAR:
  1708.                                 case XPRO_LONG:
  1709.                                 case XPRO_STRING:    if(strcmp(Opts[i] -> xpro_value,GT_STRING(GadgetArray[i])))
  1710.                                             {
  1711.                                                 Flags |= (1 << i);
  1712.  
  1713.                                                 strcpy(Opts[i] -> xpro_value,GT_STRING(GadgetArray[i]));
  1714.  
  1715.                                                 if(!OptionTitle)
  1716.                                                     NewOptions = TRUE;
  1717.                                             }
  1718.                                             break;
  1719.  
  1720.                                 default:        break;
  1721.                             }
  1722.                         }
  1723.                     }
  1724.                 }
  1725.             }
  1726.  
  1727.             ActiveGadget = NULL;
  1728.  
  1729.             RemoveGList(PanelWindow,GadgetList,(UWORD)-1);
  1730.  
  1731.             PopWindow();
  1732.  
  1733.             CloseWindow(PanelWindow);
  1734.         }
  1735.     }
  1736.  
  1737.     FreeGadgets(GadgetList);
  1738.  
  1739.     return(Flags);
  1740. }
  1741.  
  1742.     /* xpr_unlink(UBYTE *FileName):
  1743.      *
  1744.      *    Remove (delete) a given file.
  1745.      */
  1746.  
  1747. LONG __saveds __asm
  1748. xpr_unlink(register __a0 UBYTE *FileName)
  1749. {
  1750.     LONG Success = DeleteFile(FileName) ? 0 : -1;
  1751.  
  1752.     if(Success)
  1753.         LogAction(LocaleString(MSG_TERMXPR_LOGMSG_DELETE_FILE_TXT),FileName);
  1754.  
  1755.     return(Success);
  1756. }
  1757.  
  1758.     /* xpr_squery():
  1759.      *
  1760.      *    Check how many characters are present in the serial buffer.
  1761.      */
  1762.  
  1763. LONG __saveds
  1764. xpr_squery()
  1765. {
  1766.     if(WriteRequest)
  1767.     {
  1768.         WriteRequest -> IOSer . io_Command = SDCMD_QUERY;
  1769.  
  1770.         if(!DoIO(WriteRequest))
  1771.             return((LONG)WriteRequest -> IOSer . io_Actual);
  1772.     }
  1773.  
  1774.     return(-1);
  1775. }
  1776.  
  1777.     /* xpr_getptr(LONG InfoType):
  1778.      *
  1779.      *    Return a pointer to the term custom screen.
  1780.      */
  1781.  
  1782. LONG __saveds __asm
  1783. xpr_getptr(register __d0 LONG InfoType)
  1784. {
  1785.     if(InfoType == 1)
  1786.         return((LONG)Screen);
  1787.     else
  1788.         return(-1);
  1789. }
  1790.  
  1791.     /* xpr_stealopts(UBYTE *Prompt,UBYTE *Buffer):
  1792.      *
  1793.      *    Steal the contents of the options buffer (replacement
  1794.      *    for xpr_gets).
  1795.      */
  1796.  
  1797. LONG __saveds __asm
  1798. xpr_stealopts(register __a0 UBYTE *Prompt,register __a1 UBYTE *Buffer)
  1799. {
  1800.     if(Buffer)
  1801.         strcpy(ProtocolOptsBuffer,Buffer);
  1802.  
  1803.     return(1);
  1804. }
  1805.  
  1806.     /* ProtocolSetup():
  1807.      *
  1808.      *    Set up the library and options for the external protocol.
  1809.      */
  1810.  
  1811. BYTE
  1812. ProtocolSetup()
  1813. {
  1814.     UBYTE NameBuffer[40],i;
  1815.  
  1816.         /* Close the old library if still open. */
  1817.  
  1818.     if(XProtocolBase)
  1819.     {
  1820.         XProtocolCleanup(XprIO);
  1821.  
  1822.         CloseLibrary(XProtocolBase);
  1823.     }
  1824.  
  1825.         /* Clear the XPR interface buffer. */
  1826.  
  1827.     memset(XprIO,0,sizeof(struct XPR_IO));
  1828.  
  1829.         /* Copy the name of the library. */
  1830.  
  1831.     strcpy(NameBuffer,FilePart(LastXprLibrary));
  1832.  
  1833.         /* Extract the name itself (strip the `.library'). */
  1834.  
  1835.     for(i = strlen(NameBuffer) - 1 ; i >= 0 ; i--)
  1836.     {
  1837.         if(NameBuffer[i] == '.')
  1838.         {
  1839.             NameBuffer[i] = 0;
  1840.             break;
  1841.         }
  1842.     }
  1843.  
  1844.         /* Check if the transfer protocol is a sort of ZModem. */
  1845.  
  1846.     UsesZModem = FALSE;
  1847.  
  1848.     for(i = 0 ; i <= strlen(NameBuffer) - 6 ; i++)
  1849.     {
  1850.         if(!Stricmp(&NameBuffer[i],"zmodem"))
  1851.             UsesZModem = TRUE;
  1852.     }
  1853.  
  1854.         /* Obtain the protocol default settings. */
  1855.  
  1856.     if(!GetEnvDOS(NameBuffer,ProtocolOptsBuffer))
  1857.         ProtocolOptsBuffer[0] = 0;
  1858.  
  1859.         /* Initialize the interface structure. */
  1860.  
  1861.     XprIO -> xpr_filename    = ProtocolOptsBuffer;
  1862.     XprIO -> xpr_fopen    = (APTR)xpr_fopen;
  1863.     XprIO -> xpr_fclose    = (APTR)xpr_fclose;
  1864.     XprIO -> xpr_fread    = (APTR)xpr_fread;
  1865.     XprIO -> xpr_fwrite    = (APTR)xpr_fwrite;
  1866.     XprIO -> xpr_sread    = (APTR)xpr_sread;
  1867.     XprIO -> xpr_swrite    = (APTR)xpr_swrite;
  1868.     XprIO -> xpr_sflush    = (APTR)xpr_sflush;
  1869.     XprIO -> xpr_update    = (APTR)xpr_update;
  1870.     XprIO -> xpr_chkabort    = (APTR)xpr_chkabort;
  1871.     XprIO -> xpr_gets    = (APTR)xpr_gets;
  1872.     XprIO -> xpr_setserial    = (APTR)xpr_setserial;
  1873.     XprIO -> xpr_ffirst    = (APTR)xpr_ffirst;
  1874.     XprIO -> xpr_fnext    = (APTR)xpr_fnext;
  1875.     XprIO -> xpr_finfo    = (APTR)xpr_finfo;
  1876.     XprIO -> xpr_fseek    = (APTR)xpr_fseek;
  1877.     XprIO -> xpr_extension    = 4;
  1878.     XprIO -> xpr_options    = (APTR)xpr_options;
  1879.     XprIO -> xpr_unlink    = (APTR)xpr_unlink;
  1880.     XprIO -> xpr_squery    = (APTR)xpr_squery;
  1881.     XprIO -> xpr_getptr    = (APTR)xpr_getptr;
  1882.  
  1883.         /* Try to open the library. */
  1884.  
  1885.     if(XProtocolBase = (struct Library *)OpenLibrary(LastXprLibrary,0))
  1886.     {
  1887.             /* Set up the library. */
  1888.  
  1889.         TransferBits = XProtocolSetup(XprIO);
  1890.  
  1891.             /* Successful initialization? */
  1892.  
  1893.         if(!(TransferBits & XPRS_SUCCESS))
  1894.         {
  1895.             MyEasyRequest(Window,LocaleString(MSG_GLOBAL_FAILED_TO_SET_UP_PROTOCOL_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LastXprLibrary);
  1896.  
  1897.             CloseLibrary(XProtocolBase);
  1898.  
  1899.             XProtocolBase = NULL;
  1900.  
  1901.             LastXprLibrary[0] = 0;
  1902.  
  1903.             TransferBits = 0;
  1904.  
  1905.             return(FALSE);
  1906.         }
  1907.  
  1908.         if(TransferBits & XPRS_HOSTNOWAIT)
  1909.         {
  1910.             if(!HostReadBuffer)
  1911.                 HostReadBuffer = AllocVec(Config . SerBuffSize,MEMF_ANY);
  1912.         }
  1913.         else
  1914.         {
  1915.             if(HostReadBuffer)
  1916.             {
  1917.                 FreeVec(HostReadBuffer);
  1918.  
  1919.                 HostReadBuffer = NULL;
  1920.             }
  1921.         }
  1922.     }
  1923.     else
  1924.         MyEasyRequest(Window,LocaleString(MSG_GLOBAL_FAILED_TO_OPEN_PROTOCOL_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LastXprLibrary);
  1925.  
  1926.     return(TRUE);
  1927. }
  1928.  
  1929.     /* SaveProtocolOpts():
  1930.      *
  1931.      *    Save the current protocol settings to an environment variable.
  1932.      */
  1933.  
  1934. VOID
  1935. SaveProtocolOpts()
  1936. {
  1937.         /* It's time to save the altered options. */
  1938.  
  1939.     if(NewOptions && XProtocolBase)
  1940.     {
  1941.         UBYTE NameBuffer[40],i;
  1942.  
  1943.             /* Strip the `.library' part. */
  1944.  
  1945.         strcpy(NameBuffer,FilePart(LastXprLibrary));
  1946.  
  1947.         for(i = strlen(NameBuffer) - 1 ; i >= 0 ; i--)
  1948.         {
  1949.             if(NameBuffer[i] == '.')
  1950.             {
  1951.                 NameBuffer[i] = 0;
  1952.                 break;
  1953.             }
  1954.         }
  1955.  
  1956.             /* Cause the xpr.library to prompt for
  1957.              * input. We expect the library to fill
  1958.              * the prompt string with the default
  1959.              * settings. The resulting string is
  1960.              * intercepted by xpr_stealopts, saved
  1961.              * to an environment variable and will
  1962.              * serve as a reinitialization string
  1963.              * later.
  1964.              */
  1965.  
  1966.         XprIO -> xpr_filename    = NULL;
  1967.         XprIO -> xpr_gets    = (APTR)xpr_stealopts;
  1968.         XprIO -> xpr_extension    = 4;
  1969.         XprIO -> xpr_options    = (APTR)NULL;
  1970.  
  1971.         XProtocolSetup(XprIO);
  1972.  
  1973.             /* Save the options in case anything goes
  1974.              * wrong.
  1975.              */
  1976.  
  1977.         NewOptions = FALSE;
  1978.  
  1979.         SetEnvDOS(NameBuffer,ProtocolOptsBuffer);
  1980.  
  1981.             /* Reinitialize the library. */
  1982.  
  1983.         XprIO -> xpr_filename    = ProtocolOptsBuffer;
  1984.         XprIO -> xpr_gets    = (APTR)xpr_gets;
  1985.         XprIO -> xpr_extension    = 4;
  1986.         XprIO -> xpr_options    = (APTR)xpr_options;
  1987.  
  1988.         XProtocolSetup(XprIO);
  1989.     }
  1990. }
  1991.  
  1992.     /* SelectProtocol(UBYTE *Name,struct Window *ParentWindow):
  1993.      *
  1994.      *    Select a different transfer protocol library using
  1995.      *    the asl.library file requester.
  1996.      */
  1997.  
  1998. BYTE
  1999. SelectProtocol(UBYTE *Name,struct Window *ParentWindow)
  2000. {
  2001.     struct FileRequester    *AslFileRequest;
  2002.     UBYTE            *File;
  2003.     BYTE             UseNewLibrary = FALSE;
  2004.  
  2005.     File = Name;
  2006.  
  2007.     if(FilePart(File) == File)
  2008.         strcpy(SharedBuffer,"Libs:");
  2009.     else
  2010.     {
  2011.         UBYTE *Temp;
  2012.  
  2013.         strcpy(SharedBuffer,File);
  2014.  
  2015.         Temp = PathPart(SharedBuffer);
  2016.  
  2017.         Temp[0] = 0;
  2018.  
  2019.         File = FilePart(File);
  2020.     }
  2021.  
  2022.     if(AslFileRequest = (struct FileRequester *)AllocAslRequestTags(ASL_FileRequest,
  2023.         ASL_Window,    ParentWindow,
  2024.         ASL_File,    File,
  2025.         ASL_Dir,    SharedBuffer,
  2026.         ASL_Hail,    LocaleString(MSG_TERMXPR_SELECT_TRANSFER_PROTOCOL_TXT),
  2027.         ASL_FuncFlags,    FILF_NEWIDCMP,
  2028.         ASL_Pattern,    "xpr#?.library",
  2029.         ASL_OKText,    LocaleString(MSG_GLOBAL_SELECT_TXT),
  2030.     TAG_END))
  2031.     {
  2032.         if(AslRequestTags(AslFileRequest,TAG_DONE))
  2033.         {
  2034.             if(AslFileRequest -> rf_File[0])
  2035.             {
  2036.                 if(Stricmp("Libs:",AslFileRequest -> rf_Dir))
  2037.                 {
  2038.                     strcpy(SharedBuffer,AslFileRequest -> rf_Dir);
  2039.  
  2040.                     if(!AddPart(SharedBuffer,AslFileRequest -> rf_File,256))
  2041.                         strcpy(SharedBuffer,AslFileRequest -> rf_File);
  2042.                 }
  2043.                 else
  2044.                     strcpy(SharedBuffer,AslFileRequest -> rf_File);
  2045.  
  2046.                 if(SharedBuffer[0] && Stricmp(SharedBuffer,Name))
  2047.                 {
  2048.                     strcpy(LastXprLibrary,SharedBuffer);
  2049.  
  2050.                     UseNewLibrary = TRUE;
  2051.                 }
  2052.             }
  2053.         }
  2054.  
  2055.         FreeAslRequest(AslFileRequest);
  2056.     }
  2057.  
  2058.     return(UseNewLibrary);
  2059. }
  2060.